A simple attribute translator example

To understand attribute translation a little better, it's helpful to look at an example. The following translator is handles "Pound Conditional" (Poco) markup, a made-up syntax that's somewhat similar to ASP or PHP. The first step in making this translator work properly is to create a tagspec for Poco markup; this will prevent Dreamweaver from parsing the untranlsated Poco statements.

The tagspec for Poco markup looks like this:

<tagspec tag_name="poco" start_string="<#" end_string="#>"
detect_in_attribute="true" icon="poco.gif" icon_width="17" 
icon_height="15"></tagspec>

The poco.xml file containing this tagspec is stored in the Configuration/ThirdPartyTags folder along with the icon for Poco tags.

<html><head><title>Conditional Translator</title><meta http-equiv="Content-Type" content="text/html; charset="><script language="JavaScript">
/*************************************************************
 * This translator handles the following statement syntaxes: *
 * <# if (condition) then foo else bar #>                    *
 * <# if (condition) then att="foo" else att="bar" #>        *
 * <# if (condition) then att1="foo" att2="jinkies"          *
 * att3="jeepers" else att1="bar" att2="zoinks" #>           *
 *                                                           *
 * It does not handle statements with no else clause.        *
 *************************************************************/

var count = 1;

function translateMarkup(docNameStr, siteRootStr, inStr){
  var count = 1;        // Counter to ensure unique mmTranslatedValues
  var outStr = inStr;   // String that will be manipulated
  var spacer = "";      // String to manage space between encoded attributes
  var start = inStr.indexOf('<# if'); // First instance of Pound Conditional code
  
  /* Declared but not initalized. */
  var attAndValue;      // Boolean indicating whether the attribute is part of
                        // the conditional statement
  var trueStart;        // The beginning of the true case
  var falseStart;       // The beginning of the false case
  var trueValue;        // The HTML that would render in the true case
  var attName;          // The name of the attribute that is being
                        // set conditionally.
  var equalSign;        // The position of the equal sign just to the
                        // left of the <#, if there is one
  var transAtt;         // The entire translated attribute
  var transValue;       // The value that must be URL-encoded
  var back3FromStart;   // Three characters back from the start position
                        // (used to find equal sign to the left of <#
  var tokens;           // An array of all the attributes set in the true case
  var end;              // The end of the current conditional statement.
  
  
  // As long as there's still a <# conditional that hasn't been translated
  while (start != -1){
    back3FromStart = start-3;
    end = outStr.indexOf(' #>',start);
    equalSign = outStr.indexOf('="<# if',back3FromStart);
    attAndValue = (equalSign != -1)?false:true;
    trueStart = outStr.indexOf('then', start);
    falseStart = outStr.indexOf(' else', start);
    trueValue = outStr.substring(trueStart+5, falseStart);
    tokens = dreamweaver.getTokens(trueValue,' ');
    
    
    // If attAndValue is false, find out what attribute you're
    // translating by backing up from the equal sign to the
    // first space. The substring between the space and the
    // equal sign is the attribute.
    if (!attAndValue){
      for (var i=equalSign; i > 0; i--){
        if (outStr.charAt(i) == " "){
          attName = outStr.substring(i+1,equalSign);
          break;
        }
      }
      transValue = attName + '="' + trueValue + '"';
      transAtt = ' mmTranslatedValue' + count + '="' + escape(transValue) + '"';
      outStr = outStr.substring(0,end+4) + transAtt + outStr.substring(end+4);

 
    // If attAndValue is true, and tokens is greater than
    // 1, then trueValue is a series of attribute/value
    // pairs, not just one. In that case, each attribute/value
    // pair must be encoded separately and then added back
    // together to make the translated value.
    }else if (tokens.length > 1){
      transAtt = ' mmTranslatedValue' + count + '="'
      for (var j=0; j < tokens.length; j++){
        tokens[j] = escape(tokens[j]);
        if (j>0){
          spacer=" ";
        }
        transAtt += spacer + tokens[j]; 
      }
      transAtt += '"';
      outStr = outStr.substring(0,end+3) + transAtt + outStr.substring(end+3)
 
    // If attAndValue is true and tokens is not greater
    // than 1, then trueValue is a single attribute/value pair.
    // This is the simplest case, where all that is necessary is
    // to encode trueValue.
    }else{
      transValue = trueValue;
      transAtt = ' mmTranslatedValue' + count + '="' + escape(transValue) + '"';
      outStr = outStr.substring(0,end+3) + transAtt + outStr.substring(end+3);
    }
    
    // Increment the counter so that the next instance
    // of mmTranslatedValue will have a unique name, and
    // then find the next <# conditional in the code.
    count++;
    start = outStr.indexOf('<# if',end);

  }
  
  // Return the translated string.
  return outStr
}  

function getTranslatorInfo(){
  returnArray = new Array(7);
  
  returnArray[0] = "Pound_Conditional";              // The translatorClass
  returnArray[1] = "Pound Conditional Translator";   // The title
  returnArray[2] = "2";                              // The number of extensions
  returnArray[3] = "html";                           // The first extension
  returnArray[4] = "htm";                            // The second extension
  returnArray[5] = "1";                              // The number of expressions
  returnArray[6] = "<#";                             // The first expression
  
  return returnArray
}

</script></head>
<body></body></html>